--手动平面配平提示
printError("Please adjust horizontal center first!")
local pitchcontrol = peripheral.wrap("back")
pitchcontrol.setTargetSpeed(0)
--函数
function sec(i)
    local seci = 1 / math.cos(math.rad(i))
    return seci
end
function tan(i)
    local tani = math.tan(math.rad(i))
    return tani
end
function round(input , num)
    local remain = input % num
    if remain < 0 then
        return input - remain - num
    elseif remain > 0 then
        return input - remain
    else
        return input
    end
end
--炮管长度输入
local k = nil
print("Import barrel length:(From cannon mount to the end of barrel)")
repeat
    k = tonumber(io.read())
    if type(k) ~= "number" then
        printError("Wrong format, please try again.")
        k = nil
    elseif k < 1 then
        printError("Out of range, please try again.")
        k = nil
    elseif k % 1 ~= 0 then
        printError("Wrong format, please try again.")
        k = nil
    end
until k ~= nil
--发射药装药输入（用于瓦基大冒险高装药）
local n = nil
print("Import powder power:")
repeat
    n = tonumber(io.read())
    if type(n) ~= "number" then
        printError("Wrong format, please try again.")
        n = nil
    elseif n < 1 then
        printError("Out of range, please try again.")
        n = nil
    elseif n % 1 ~= 0 then
        printError("Wrong format, please try again.")
        n = nil
    end
until n ~= nil
--垂直修正
local ycor = nil
print("Import Y correction:")
repeat
    ycor = tonumber(io.read())
    if type(ycor) ~= "number" then
        printError("Wrong format, please try again.")
        ycor = nil
    elseif ycor % 1 ~= 0 then
        printError("Wrong format, please try again.")
        ycor = nil
    end
until ycor ~= nil
local targetpos = { x = nil , y = nil , z = nil }
local currentpitch = 0

--主功能段

while true do
    ::start::
    --获取船体重心世界坐标
    local pos = ship.getWorldspacePosition()
    --炮管轴世界坐标
    local cannonpos = { x = pos.x , y = pos.y + ycor , z = pos.z }
    print("Enter target position:")
    targetpos.x = io.read() + 0.5
    targetpos.y = io.read() + 0.5
    targetpos.z = io.read() + 0.5
    --炮塔对目标世界坐标系相对距离
    local delta = {
        x = targetpos.x - cannonpos.x ,
        y = targetpos.y - cannonpos.y ,
        z = targetpos.z - cannonpos.z
    }
    --直线水平距离
    local w = math.sqrt(delta.x ^ 2 + delta.z ^ 2)
    --俯仰计算，二分法
    local cannonpitch = nil
    local miss = 0.2
    local pitch1 = -10
    local pitch2 = 85
    local pitch = 0
    local y_ccl = 0
    repeat
        local y_ccl1 = ((5 * sec(pitch1) / n) + tan(pitch1)) * w + 500 * math.log(1 - (w * sec(pitch1) - k) / (100 * n)) - 5 * k / n
        local y_ccl2 = ((5 * sec(pitch2) / n) + tan(pitch2)) * w + 500 * math.log(1 - (w * sec(pitch2) - k) / (100 * n)) - 5 * k / n
        if delta.y - y_ccl1 < y_ccl2 - delta.y then
            pitch2 = (pitch1 + pitch2) / 2
            y_ccl = y_ccl1
            pitch = pitch1
        else
            pitch1 = (pitch1 + pitch2) / 2
            y_ccl = y_ccl2
            pitch = pitch2
        end
        if math.abs(delta.y - y_ccl) <= miss and miss < 2 then --误差内选取
            cannonpitch = pitch
            break
        elseif miss >= 2 then --误差外返回信息
            cannonpitch = "out of range"
            print("Negative, out of range.")
            break
        end
        if math.abs(pitch1 - pitch2) < 0.375 then --精度外提高误差允许范围重置
            miss = miss + 0.2
            pitch1 = -10
            pitch2 = 85
            pitch = 0
            y_ccl = 0
        end
    until cannonpitch ~= nil
    if cannonpitch == "out of range" then
        goto start
    end
    --目标方位计算
    local deltapitch = cannonpitch - currentpitch
    local pitchoutput = -math.floor(deltapitch / 0.375 + 0.5)
    pitchcontrol.setTargetSpeed(pitchoutput)
    currentpitch = currentpitch + deltapitch
    sleep(0.45)
    pitchcontrol.setTargetSpeed(0)
end
